<template>
  <CustomModal
    title="语音控制"
    v-model="visible"
    isTabbar
    :showCancelButton="status !== 'success'"
    :showConfirmButton="status !== 'recognize'"
    :confirmText="status === 'listen' ? '说完了' : '执行'"
    class="voice-control"
    @close="handleClose"
    @confirm="handleConfirm"
  >
    <view
      class="modal-content"
      :style="{
        'margin-top': status === 'success' ? '33rpx' : '51rpx'
      }"
    >
      <view v-if="status === 'listen'" class="container">
        <image
          :src="getViteImageUrl('system/voiceRecognize.png')"
          mode="aspectFit"
          class="voice-icon"
        />
        <view class="content-text">正在聆听{{ contentText }}</view>
      </view>
      <view v-if="status === 'recognize'" class="container">
        <image
          :src="getViteImageUrl('recipe/loading.png')"
          mode="aspectFit"
          class="loading-icon"
        />
        <view class="content-text">正在识别语音指令......</view>
      </view>
      <view v-if="status === 'success'" class="container">
        <view class="form-title-container">
          <image
            :src="getViteImageUrl('system/wranCircleFill.png')"
            mode="aspectFit"
            class="wran-icon"
          />
          <view class="form-title">识别到语音命名如下</view>
        </view>
        <scroll-view class="scroll-content" scroll-y>
          <uni-forms v-if="type === 'default'" ref="uFormRef" :modelValue="formData" :rules="rules">
            <uni-forms-item name="deviceSn">
              <template #label>
                <view class="nw-label">烹饪设备</view>
              </template>
              <view class="uss-form-select">
                <nw-PickerSelect
                  v-model="formData.deviceSn"
                  :columns="[deviceList]"
                  style="width: 100%; max-width: 100%"
                  @confirm="handleDeviceConfirm"
                />
              </view>
            </uni-forms-item>
            <uni-forms-item name="cookingMethod">
              <template #label>
                <view class="nw-label">烹饪方法</view>
              </template>
              <view class="uss-form-select">
                <nw-PickerSelect
                  v-model="formData.cookingMethod"
                  :columns="[g_options.cookingMethodOptions]"
                  style="width: 100%; max-width: 100%"
                />
              </view>
            </uni-forms-item>
            <uni-forms-item name="recipeId">
              <template #label>
                <view class="nw-label">菜谱名称</view>
              </template>
              <!-- <nw-Input v-model="formData.name" label="菜谱名称" /> -->
              <view class="uss-form-select">
                <nw-PickerSelect
                  v-model="formData.recipeId"
                  :columns="[recipeList]"
                  style="width: 100%; max-width: 100%"
                  @confirm="handleRecipeConfirm"
                />
              </view>
            </uni-forms-item>
            <uni-forms-item>
              <template #label>
                <view class="nw-label">烹饪份量</view>
              </template>
              <view class="nw-value">
                {{
                  g_options.getOptionText(
                    recipeWeightOptions,
                    formData.cookCount,
                    '--'
                  )
                }}
              </view>
              <!-- <view class="uss-form-select">
                <nw-PickerSelect
                  v-model="formData.cookCount"
                  :columns="[recipeWeightOptions]"
                  style="width: 100%; max-width: 100%"
                />
              </view> -->
            </uni-forms-item>
            <uni-forms-item>
              <template #label>
                <view class="nw-label">菜系类别</view>
              </template>
              <view class="nw-value">
                {{
                  g_options.getOptionText(
                    recipeCookStyleOptions,
                    formData.cookStyle,
                    '--'
                  )
                }}
              </view>
              <!-- <view class="uss-form-select">
                <nw-PickerSelect
                  v-model="formData.cookStyle"
                  :columns="[recipeCookStyleOptions]"
                  style="width: 100%; max-width: 100%"
                />
              </view> -->
            </uni-forms-item>
            <uni-forms-item>
              <template #label>
                <view class="nw-label">口味风格</view>
              </template>
              <view class="nw-value">
                {{
                  g_options.getOptionText(
                    recipeTasteOptions,
                    formData.tasteStyle,
                    '--'
                  )
                }}
              </view>
              <!-- <view class="uss-form-select">
                <nw-PickerSelect
                  v-model="formData.tasteStyle"
                  :columns="[recipeTasteOptions]"
                  style="width: 100%; max-width: 100%"
                />
              </view> -->
            </uni-forms-item>
          </uni-forms>
          <manual ref="manualFormRef" :voiceData="voiceResponse" :analysis-source="analysisSource" v-else />
        </scroll-view>
        <view class="count-down-container">
          <view class="cdc-text">{{ rawText }}</view>
          <view class="chart-container">
            <qiun-data-charts
              type="arcbar"
              :opts="opts"
              :animation="false"
              :chartData="chartData"
            />
          </view>
        </view>
      </view>
    </view>
  </CustomModal>
  <up-toast ref="uToastRef" />
</template>

<script setup>
// #ifdef APP-PLUS
// import voiceRecorder from '@/utils/voiceRecorder.js'
// #endif
import useVoice from './useVoice'
import useNumberConvert from '../../mixins/useNumberConvert'
import { deviceProtocolRecipeService } from '@/service/deviceProtocolRecipeService.js'
import manual from './manual.vue'

defineOptions({
  name: 'VoiceControl',
  inheritAttrs: false
})
const emit = defineEmits(['confirm'])

const props = defineProps({
  type: {
    type: String,
    default: 'default',
    vaidator: val => ['default', 'manual'].includes(val)
  },
  analysisSource: {
    type: Object,
    default: () => ({})
  }
})

const visible = defineModel({
  type: Boolean,
  default: false
})
const status = ref('listen') // listen: 聆听, recognize: 识别, stop: 停止, error: 错误, success: 成功
const contentText = ref('.') // 文本加载中
let textTimer = null
// 表单参数
const { cookingItemList } = storeToRefs(useCookingStore())
const { userInfo } = storeToRefs(useUserStore())
const { recipeLibraryList } = storeToRefs(useRecipeStore())
const recipeList = computed(() => {
  return g_.cloneDeep(recipeLibraryList.value).map(item => {
    return {
      ...item,
      label: item.name,
      value: item.id
    }
  })
})
const uToastRef = ref(null)
const uFormRef = ref(null)
const manualFormRef = ref(null)
const formData = ref({
  // cookingDevice: '',
  deviceSn: [],
  cookingMethod: ['0'],
  recipeId: [],
  // name: [],
  cookCount: 1,
  cookStyle: '',
  tasteStyle: ''
})
const rawText = ref('')
// 校验规则
const rules = {
  deviceSn: {
    rules: g_rules.selectRule('烹饪设备')
  },
  cookingMethod: {
    rules: g_rules.selectRule('烹饪方法')
  },
  recipeId: {
    rules: g_rules.selectRule('菜谱名称')
  }
  // cookCount: {
  //   rules: g_rules.selectRule('烹饪份量')
  // },
  // cookStyle: {
  //   rules: g_rules.selectRule('菜系类别')
  // },
  // tasteStyle: {
  //   rules: g_rules.selectRule('口味风格')
  // }
}
const deviceStore = useDeviceStore()
const recipeStore = useRecipeStore()
const {
  // 列表参数
  recipeWeightOptions,
  recipeCookStyleOptions,
  recipeTasteOptions
} = storeToRefs(recipeStore)
const { bindDeviceList } = storeToRefs(deviceStore)
const deviceList = computed(() => {
  return g_.cloneDeep(bindDeviceList.value).filter(item => {
    if (item.status * 1 === g_i.device.DeviceStatus.Idle) {
      item.value = item.sn
      item.label = item.name
      return item
    }
  })
})
// 倒计时参数
const countDown = ref(5)
let timer = null
// 进度圆环参数
const opts = computed(() => {
  return {
    padding: [0, 0, 0, 0],
    color: ['#1890FF'],
    update: true,
    title: {
      name: `${countDown.value}秒`,
      fontSize: g_utils.rpxToPx(18),
      color: '#27BE87'
    },
    subtitle: {
      name: ''
    },
    extra: {
      arcbar: {
        type: 'circle',
        width: g_utils.rpxToPx(6),
        backgroundColor: '#f7f7f7',
        startAngle: 1.5,
        endAngle: 0.25,
        radius: g_utils.rpxToPx((89 - 6) / 2),
        gap: 0
      }
    }
  }
})
const chartData = computed(() => {
  return {
    series: [
      {
        name: '',
        color: '#2fc25b',
        data: 1 - countDown.value / 5
      }
    ]
  }
})
// 音频参数
const innerAudioContext = uni.createInnerAudioContext()
innerAudioContext.autoplay = true
innerAudioContext.volume = 1

// 文本动画显示
const startTextTimer = _ => {
  textTimer && clearInterval(textTimer)
  textTimer = setInterval(() => {
    if (contentText.value.length >= 6) {
      contentText.value = ''
    }
    contentText.value += '.'
  }, 300)
}

const stopTextTimer = _ => {
  textTimer && clearInterval(textTimer)
  textTimer = null
}

// 执行倒计时
const startCountDown = _ => {
  timer && clearInterval(timer)
  timer = setInterval(() => {
    countDown.value--
    if (countDown.value <= 0) {
      stopCountDown()
      successFunc()
    }
  }, 1000)
}
const stopCountDown = _ => {
  timer && clearInterval(timer)
  timer = null
}

watch(
  () => status.value,
  nv => {
    console.log('status.value-watch', nv)
    stopTextTimer()
    stopCountDown()
    if (nv === 'listen') {
      startTextTimer()
    } else if (nv === 'success') {
      startCountDown()
    }
  },
  {
    immediate: true,
    deep: true
  }
)

const {
  voiceSuccess,
  voiceResponse,
  startVoice,
  stopVoice
} = useVoice({uToastRef, type: props.type})

watch(
  () => voiceSuccess.value,
  nv => {
    if (nv) {
      status.value = 'success'
      rawText.value = voiceResponse.value.rawText

      // 语音转菜谱指令处理
      if (props.type === 'default') {
        voiceToRecipe(voiceResponse.value)
        
      } else if (props.type === 'manual') {
        // 手动模式-不处理
      }
      
    } else {
      status.value = 'listen'
    }
   
  }
)

onMounted(async _ => {
  // #ifdef APP-PLUS
  // 录音操作
  status.value = 'listen'
  startVoice()
  // voiceRecorderNative.start()
  // voiceRecorderNative.onStop(res => {
  //   const filePath = res.filePath
  //   console.log('recorder onStop-平台绝对路径', filePath)
  //   lingxinVoiceToText(filePath)
  // })
  // #endif
})

onUnmounted(_ => {
  console.log('onUnmounted')
  stopTextTimer()
  stopCountDown()
})

// 语音播报
// const lingxinTextToVoice = _ => {
//   lingxinApiService
//     .textToVoice('测试')
//     .then(filePath => {
//       console.log('文本转语音成功-filePath: ', filePath)
//       innerAudioContext.src = filePath
//       innerAudioContext.play()
//     })
//     .catch(e => {
//       console.log('文本转语音失败：', e)
//     })
// }
const { convertNumber } = useNumberConvert()
// 语音识别--菜谱
const voiceToRecipe = (jsonData) => {
    const tempDeviceName = convertNumber(jsonData.deviceName)
    
    const deviceRow = deviceList.value.find(
      item => {
        const strs = [convertNumber(item.name), convertNumber(item.nickName)]
        return strs.find(val => val === tempDeviceName)
      } 
    )
    const recipeRow = recipeList.value.find(
      item => item.name === jsonData.recipe
    )
    formData.value = {
      ...formData.value,
      deviceSn: deviceRow ? [deviceRow.sn] : [],
      recipeId: recipeRow ? [recipeRow.id] : [],
      cookCount: jsonData.count || 1,
      cookStyle: recipeRow?.cookStyle || '',
      tasteStyle: recipeRow?.tasteStyle || ''
    }
    
}

const handleClose = _ => {
  console.log('handleClose')
  status.value = 'stop'
  stopTextTimer()
  stopCountDown()
}

const handleConfirm = _ => {
  console.log('handleConfirm')
  if (status.value === 'listen') {
    // #ifdef APP-PLUS
    stopVoice()
    status.value = 'recognize'
    // #endif
  } else if (status.value === 'success') {
    successFunc()
  }
}

function recipeDataOper() {
  uni.showLoading({ title: '指令处理中...', mask: true })
  // 本地数据同步
  const deviceRow = bindDeviceList.value.find(
    item => item.sn === formData.value.deviceSn[0]
  )
  const recipeRow = recipeList.value.find(
    item => item.id === formData.value.recipeId[0]
  )
  console.log('deviceRow', deviceRow)
  console.log('recipeRow', recipeRow)
  const allIngredList = (recipeRow.stepList || []).filter(item => {
    if (item.ingredientType === 'material') {
      // 计算步骤食材的总重量
      item.totalGoal = item?.materialList.reduce((prev, curr) => {
        return prev + curr.goal
      }, 0)
      return true
    }
  })
  console.log('allIngredList', allIngredList)
  // 更新设备信息的调料名称与调料编码
  console.log('设备信息（前）：', deviceRow)
  console.log('步骤食材信息（前）：', allIngredList)
  deviceRow.peripheralList.forEach(item => {
    if (item.type === 1) {
      const ingredItem = allIngredList[parseInt(item.tag.substring(2)) - 1]
      if (ingredItem) {
        item.ingredientName = ingredItem.ingredientName
        item.ingredientCode = ingredItem.target
      } else {
        item.ingredientName = ''
        item.ingredientCode = ''
      }
    }
  })
  console.log('设备信息（后）：', deviceRow)

  // 烹饪记录存储
  cookingItemList.value.push(
    g_i.apiDataFormat(
      {
        cookingId: g_utils.getUuid(),
        deviceSn: deviceRow.sn,
        deviceName: deviceRow.name,
        recipeId: recipeRow.id,
        recipeName: recipeRow.name,
        cookCount: formData.value.cookCount,
        tasteStyle: recipeRow.tasteStyle,
        operatorUserId: userInfo.value.userId,
        createTime: Date.now()
      },
      g_i.cooking.cookItemInfo
    )
  )

  // 电子称需要在发送菜谱之前下发，需要先确认设备绑定的电子称信息，绑定的才发
  if (deviceRow.bindElectronic) {
    const weights = Object.assign(
      {},
      ...Array.from({ length: 4 }, (_, i) => ({
        [`weight${i + 1}`]: allIngredList[i]?.totalGoal || 0
      }))
    )
    deviceProtocolEquipmentService
      .electronicScaleFoodPreparation(deviceRow.sn, weights)
      .then(r => {
        console.log('electronicScaleFoodPreparation-发送消息成功：', r)
      })
      .catch(e => {
        console.log('electronicScaleFoodPreparation-发送消息失败：', e)
        uToastRef.value.show({
          type: 'error',
          message: e
        })
      })
  }

  // 执行设备协议操作:下发菜谱、开始炒菜、油烟机命令
  deviceProtocolRecipeService
    .sendRecipe(deviceRow, recipeRow)
    .then(r => {
      console.log('sendRecipe-发送消息成功：', r)
      // 开始炒菜
      deviceProtocolRecipeService
        .startCooking(deviceRow.sn, recipeRow.id)
        .then(r => {
          console.log('startCooking-发送消息成功：', r)
          // 更新设备的状态值为炒菜中
          deviceStore.updateDeviceStatus(
            deviceRow.sn,
            g_i.device.DeviceStatus.Cooking
          )
          visible.value = false
          emit('confirm')
        })
        .catch(e => {
          console.log('startCooking-发送消息失败：', e)
          uToastRef.value.show({
            type: 'error',
            message: e
          })
        })
        .finally(() => uni.hideLoading())
      // 发送油烟机指令
      if (deviceRow.bindOil) {
        deviceProtocolEquipmentService
          .rangeHoodFanControl(deviceRow.sn, 1, 1)
          .then(r => {
            console.log('rangeHoodFanControl-发送消息成功：', r)
          })
          .catch(e => {
            console.log('rangeHoodFanControl-发送消息失败：', e)
            uToastRef.value.show({
              type: 'error',
              message: e
            })
          })
      }
    })
    .catch(e => {
      console.log('sendRecipe-发送消息失败：', e)
      uToastRef.value.show({
        type: 'error',
        message: e
      })
      uni.hideLoading()
    })
}

const manualDataOper = (data) => {
  emit('confirm', data)
  visible.value = false
}

// 成功之后的执行函数
const successFunc = _ => {
  if (props.type == 'manual') {
    manualFormRef.value.done().then(res => {
      manualDataOper(res)
    }).catch(err => {
      console.log('err', err)
    })
   
  } else {
    uFormRef.value
    .validate()
    .then(res => {
      console.log('successFunc', formData.value)
      // const newFormData = {
      //   ...formData.value,
      //   deviceSn: formData.value.deviceSn[0] ?? '',
      //   recipeId: formData.value.recipeId[0] ?? '',
      //   cookingMethod: formData.value.cookingMethod[0] ?? ''
      // }
      // console.log('newFormData', newFormData)
      recipeDataOper()
    })
    .catch(err => {
      console.log('err', err)
    })
  }
  
}

const handleDeviceConfirm = e => {
  console.log('handleDeviceConfirm', e, formData.value)
  const value = e.value[0]
  formData.value.deviceSn = [value.sn]
}

const handleRecipeConfirm = e => {
  console.log('handleRecipeConfirm', e, formData.value)
  const value = e.value[0]
  formData.value.cookCount = value.cookCount
  formData.value.cookStyle = value.cookStyle
  formData.value.tasteStyle = value.tasteStyle
}
</script>

<style lang="scss" scoped>
.modal-content {
  display: flex;
  flex-direction: column;
  margin: 51rpx 0 39rpx;
}

.voice-control :deep(.nw-button-wrap) {
  .nw-dialog-cancel-button {
    background-color: #fff !important;
    border-color: #d7dbec !important;
    .u-button__text {
      color: #333 !important;
    }
  }
}

.container {
  display: flex;
  flex-direction: column;
  .voice-icon {
    width: 37rpx;
    height: 55rpx;
    margin: 0 auto;
  }

  .loading-icon {
    width: 62rpx;
    height: 62rpx;
    margin: 0 auto;
    animation: spin 2s linear infinite;
  }

  @keyframes spin {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }

  .content-text {
    margin: 35rpx 0 12rpx 0;
    line-height: 26rpx;
    text-align: center;
    font-size: 27rpx;
    font-weight: 400;
    color: var(--color-333);
  }
}

.form-title-container {
  display: flex;
  align-items: center;
  margin-bottom: 32rpx;
  .wran-icon {
    width: 23rpx;
    height: 23rpx;
    padding-top: 4rpx;
  }
  .form-title {
    margin-left: 9rpx;
    font-size: 22rpx;
    font-weight: bold;
    color: #333;
  }
}

:deep(.uni-forms) {
  padding-bottom: 0;

  .nw-label {
    width: 108rpx;
  }

  .nw-value {
    display: flex;
    align-items: center;
    height: 40rpx;
    margin-left: 10rpx;
    font-size: 22rpx;
    font-weight: 400;
    color: var(--color-333);
  }

  // zxz-uni-data-select多选择框-样式
  .uss-form-select {
    .nw-picker-container {
      width: 100%;
      max-width: 100%;
      height: 40rpx;
      min-height: 40rpx;
      .input-text {
        font-size: 22rpx;
      }
    }
  }
}

.count-down-container {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 21rpx;
  .cdc-text {
    line-height: 26rpx;
    text-align: center;
    font-size: 24rpx;
    font-weight: 400;
    color: var(--color-333);
  }
  .chart-container {
    width: 89rpx;
    height: 89rpx;
    margin-left: 41rpx;
  }
}
</style>
